home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / extras / programm / a56 / src / a56.y < prev    next >
Text File  |  1995-04-27  |  41KB  |  1,824 lines

  1. %{
  2. /*******************************************************
  3.  *
  4.  *  a56 - a DSP56001 assembler
  5.  *
  6.  *  Written by Quinn C. Jensen
  7.  *  July 1990
  8.  *
  9.  *******************************************************/
  10.  
  11. /*
  12.  * Copyright (C) 1990-1994 Quinn C. Jensen
  13.  *
  14.  * Permission to use, copy, modify, distribute, and sell this software
  15.  * and its documentation for any purpose is hereby granted without fee,
  16.  * provided that the above copyright notice appear in all copies and
  17.  * that both that copyright notice and this permission notice appear
  18.  * in supporting documentation.  The author makes no representations
  19.  * about the suitability of this software for any purpose.  It is
  20.  * provided "as is" without express or implied warranty.
  21.  *
  22.  */
  23.  
  24. /*
  25.  *  a56.y - The YACC grammar for the assembler.
  26.  *
  27.  *  Note:  This module requires a "BIG" version of YACC.  I had to
  28.  *  recompile YACC in the largest mode available.
  29.  *
  30.  *  Other notes:
  31.  *
  32.  *  MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure
  33.  *  out which form to use.
  34.  *
  35.  */
  36.  
  37. #include "a56.h"
  38.  
  39. unsigned int w0, w1;            /* workspace for the actual generated code */
  40. BOOL uses_w1;                    /* says whether w1 is alive */
  41. unsigned int pc;                /* current program counter */
  42. int seg;                        /* current segment P: X: Y: or L: */
  43.  
  44. int just_rep = 0;                /* keeps track of REP instruction */
  45. int substatement = 0;            /* in a substatement */
  46. BOOL long_symbolic_expr = FALSE; /* a parser flag */
  47. char *new_include = NULL;        /* file to be included */
  48.  
  49. /* listing stuff */
  50.  
  51. char segs[] = "PXYL";
  52. extern BOOL list_on_next;        /* listing to turn on or off */
  53. BOOL list_on;                    /* listing on at the moment */
  54. extern char *cur_line;            /* points to line being lex'd */
  55. char list_buf[1024 + 80];        /* listing buffer */
  56. char list_buf2[1024 + 80];        /* listing buffer for two-line code */
  57. BOOL uses_buf2 = FALSE;            /* list_buf2 is alive */
  58. BOOL list_print_line = FALSE;    /* whether or not to print line in listing */
  59. char *spaces(), *luntab();
  60.  
  61. struct n binary_op();
  62. struct n unary_op();
  63. struct n sym_ref();
  64.  
  65. #define R_R6                0x0001
  66. #define R_R5                0x0002
  67. #define R_R4                0x0004
  68. #define R_DATA_ALU_ACCUM    0x0008
  69. #define R_CTL_REG            0x0010
  70. #define R_FUNKY_CTL_REG        0x0020
  71. #define R_SDX                0x0040
  72. #define R_SDY                0x0080
  73. #define R_LSD                0x0100
  74. #define R_AB                0x0200
  75. #define R_XREG                0x0400
  76. #define R_YREG                0x0800
  77. /* registers to which short immediate move is an unsigned int */
  78. #define R_UINT                0x1000
  79. /* registers to which short immediate move is an signed frac */
  80. #define R_SFRAC                0x2000
  81. %}
  82.  
  83. %union {
  84.     int ival;            /* integer value */
  85.     struct n n;            /* just like in struct sym */
  86.     double dval;        /* floating point value */
  87.     char *sval;            /* string */
  88.     int cval;            /* character */
  89.     char cond;            /* condition */
  90.     struct regs {
  91.         int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
  92.         int sdx, sdy, lsd, ab, xreg, yreg;
  93.         int flags;
  94.     } regs;
  95.     struct ea {
  96.         int mode;
  97.         int ext;
  98.         int pp;
  99.     } ea;
  100. }
  101.  
  102. %token <n> CHEX CDEC FRAC 
  103. %token <ival> AREG BREG MREG NREG RREG XREG YREG
  104. %token <ival> OP OPA OPP
  105. %token <cond> OP_JCC OP_JSCC OP_TCC
  106. %token <sval> SYM
  107. %token <sval> STRING
  108. %token <cval> CHAR
  109. %token XMEM
  110. %token YMEM
  111. %token LMEM
  112. %token PMEM
  113. %token AAAA
  114. %token A10
  115. %token BBBB
  116. %token B10
  117. %token AABB
  118. %token BBAA
  119. %token XXXX
  120. %token YYYY
  121. %token SR
  122. %token MR
  123. %token CCR
  124. %token OMR
  125. %token SP
  126. %token SSH
  127. %token SSL
  128. %token LA
  129. %token LC
  130. %token EOL
  131. %token EOS
  132. %token LEXBAD
  133.  
  134. %token OP_ABS
  135. %token OP_ADC
  136. %token OP_ADD
  137. %token OP_ADDL
  138. %token OP_ADDR
  139. %token OP_ASL
  140. %token OP_ASR
  141. %token OP_CLR
  142. %token OP_CMP
  143. %token OP_CMPM
  144. %token OP_DIV
  145. %token OP_MAC
  146. %token OP_MACR
  147. %token OP_MPY
  148. %token OP_MPYR
  149. %token OP_NEG
  150. %token OP_NORM
  151. %token OP_RND
  152. %token OP_SBC
  153. %token OP_SUB
  154. %token OP_SUBL
  155. %token OP_SUBR
  156. %token OP_TFR
  157. %token OP_TST
  158. %token OP_AND
  159. %token OP_ANDI
  160. %token OP_EOR
  161. %token OP_LSL
  162. %token OP_LSR
  163. %token OP_NOT
  164. %token OP_OR
  165. %token OP_ORI
  166. %token OP_ROL
  167. %token OP_ROR
  168. %token OP_BCLR
  169. %token OP_BSET
  170. %token OP_BCHG
  171. %token OP_BTST
  172. %token OP_DO
  173. %token OP_ENDDO
  174. %token OP_LUA
  175. %token OP_MOVE
  176. %token OP_MOVEC
  177. %token OP_MOVEM
  178. %token OP_MOVEP
  179. %token OP_ILLEGAL
  180. %token OP_INCLUDE
  181. %token OP_JMP
  182. %token OP_JCLR
  183. %token OP_JSET
  184. %token OP_JSR
  185. %token OP_JSCLR
  186. %token OP_JSSET
  187. %token OP_NOP
  188. %token OP_REP
  189. %token OP_RESET
  190. %token OP_RTI
  191. %token OP_RTS
  192. %token OP_STOP
  193. %token OP_SWI
  194. %token OP_WAIT
  195. %token OP_EQU
  196. %token OP_ORG
  197. %token OP_DC
  198. %token OP_DS
  199. %token OP_DSM
  200. %token OP_END
  201. %token OP_PAGE
  202. %token OP_PSECT
  203. %token OP_ALIGN
  204. %token OP_INT
  205. %token SHL
  206. %token SHR
  207.  
  208. %type <n> num num_or_sym 
  209. %type <n> num_or_sym_expr
  210. %type <n> expr
  211. %type <n> ix
  212. %type <n> ix_long
  213.  
  214. %type <ival> abs_addr abs_short_addr io_short_addr 
  215. %type <ival> a_b x_or_y ea b5_10111_max
  216. %type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
  217. %type <ival> ea_short
  218. %type <ival> prog_ctl_reg
  219. %type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
  220. %type <ival> mpy_arg mpy_srcs plus_minus
  221. %type <ival> sd3
  222. %type <ival> funky_ctl_reg tcc_sd space
  223. %type <sval> opt_label
  224.  
  225. %type <regs> regs
  226. %type <ea> movep_ea_pp
  227.  
  228. %left '|'
  229. %left '^'
  230. %left SHL SHR
  231. %left '&'
  232. %left '+' '-'
  233. %left '*' '/' '%'
  234. %right '~'
  235.  
  236. %start input
  237.  
  238. %%
  239.  
  240. /*%%%********************* top syntax ***********************/
  241.  
  242. input    :    /* empty */
  243.     |    input statement
  244.     ;
  245.  
  246. statement
  247.     :    good_stuff EOL
  248.             {
  249.             if(pass == 2 && list_on && list_print_line) {
  250.                 printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
  251.                     list_buf, substatement == 0 ? luntab(cur_line) : "");
  252.                 if(uses_buf2)
  253.                     printf(ldebug ? "\n(%s|)\n" : "%s\n",
  254.                         list_buf2);
  255.                 list_buf[0] = list_buf2[0] = '\0';
  256.             }
  257.             curline++;
  258.             uses_buf2 = FALSE;
  259.             list_print_line = TRUE;
  260.             list_on = list_on_next;
  261.             substatement = 0;
  262.             if(NOT check_psect(seg, pc) && pass == 2)
  263.                 yyerror("%04X: psect violation", pc);
  264.             }
  265.     |    good_stuff EOS
  266.             {
  267.             if(pass == 2 && list_on && list_print_line) {
  268.                 printf(ldebug ? "\n(%s" : "%s", list_buf);
  269.                 if(substatement == 0)
  270.                     printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line));
  271.                 else
  272.                     printf(ldebug ? ")\n" : "\n");
  273.                 if(uses_buf2)
  274.                     printf(ldebug ? "\n(%s|)\n" : "%s\n",
  275.                         list_buf2);
  276.                 list_buf[0] = list_buf2[0] = '\0';
  277.             }
  278.             substatement++;
  279.             uses_buf2 = FALSE;
  280.             list_print_line = TRUE;
  281.             list_on = list_on_next;
  282.             if(NOT check_psect(seg, pc) && pass == 2)
  283.                 yyerror("%04X: psect violation", pc);
  284.             }
  285.     |    error EOL
  286.             {curline++; substatement = 0;}
  287.     ;
  288.  
  289. good_stuff
  290.     :    /* empty */
  291.             {sprintf(list_buf, "%s", spaces(0));}
  292.     |    cpp_droppings
  293.             {list_print_line = FALSE;}
  294.     |    assembler_ops
  295.             {long_symbolic_expr = FALSE;}
  296.     |    label_field operation_field
  297.             {char *printcode();
  298.             if(pass == 2) {
  299.                 gencode(seg, pc, w0);
  300.                 sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0));
  301.                 pc++;
  302.                 if(uses_w1) {
  303.                     gencode(seg, pc, w1);
  304.                     sprintf(list_buf2, "%c:%04X %s", segs[seg], pc,
  305.                                printcode(w1 & 0xFFFFFF));
  306.                     uses_buf2++;
  307.                     pc++;
  308.                 }
  309.             } else {
  310.                 pc++;
  311.                 if(uses_w1)
  312.                     pc++;
  313.             }
  314.             w0 = w1 = 0; uses_w1 = FALSE; 
  315.             long_symbolic_expr = FALSE;}
  316.     |    SYM 
  317.             {sym_def($1, INT, pc);
  318.             free($1);
  319.             if(pass == 2 && list_on) {
  320.                 sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8));
  321.             long_symbolic_expr = FALSE;
  322.             }}
  323.     ;
  324.  
  325. cpp_droppings
  326.     :    '#' num STRING
  327.             {if(strlen($3) > 0)
  328.                 curfile = $3;
  329.             else
  330.                 curfile = "<stdin>";
  331.             curline = $2.val.i - 1;}
  332.     ;
  333.  
  334. assembler_ops
  335.     :    SYM OP_EQU expr
  336.             {sym_def($1, $3.type, $3.val.i, $3.val.f);
  337.             free($1);
  338.             if(pass == 2 && list_on) {
  339.                 if($3.type == INT)
  340.                     sprintf(list_buf, "%06X%s",
  341.                         $3.val.i & 0xFFFFFF,
  342.                         spaces(14-8));
  343.                 else
  344.                     sprintf(list_buf, "%10g%s", $3.val.f,
  345.                         spaces(14-4));
  346.             }}
  347.     |    OP_ALIGN expr
  348.             {int ival = n2int($2);
  349.             if($2.type == UNDEF) {
  350.                 yyerror("illegal forward reference");
  351.             } else if (ival <= 1) {
  352.                 yyerror("%d: illegal alignment", ival);
  353.             } else {
  354.                 if(pc % ival != 0)
  355.                     pc += ival - pc % ival;
  356.             }
  357.             if(pass == 2 && list_on)
  358.                 sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
  359.                     spaces(14-8));
  360.             }
  361.     |    OP_PSECT SYM
  362.             {struct psect *pp = find_psect($2);
  363.             if(NOT pp) {
  364.                 if(pass == 2)
  365.                     yyerror("%s: undefined psect", $2);
  366.             } else {
  367.                 seg = pp->seg;
  368.                 pc = pp->pc;
  369.                 set_psect(pp);
  370.                 if(pass == 2 && list_on)
  371.                     sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
  372.                         spaces(14-8));
  373.             }
  374.             free($2);}
  375.     |    OP_PSECT SYM space expr ':' expr
  376.             {new_psect($2, $3, n2int($4), n2int($6));
  377.             if(pass == 2 && list_on)
  378.                 sprintf(list_buf, "%c:%04X %04X%s", 
  379.                     segs[$3], n2int($4), n2int($6), spaces(14-8+4+1));
  380.             }
  381.     |    OP_ORG space expr
  382.             {pc = n2int($3);
  383.             seg = $2;
  384.             if(pass == 2 && list_on)
  385.                 sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
  386.                     spaces(14-8));
  387.             }
  388.     |    OP_ORG space expr ',' space expr
  389.             {pc = n2int($3);
  390.             seg = $2;
  391.             if(pass == 2 && list_on)
  392.                 sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
  393.                     spaces(14-8));
  394.             }
  395.     |    label_field OP_DC dc_list
  396.     |    label_field OP_DS expr
  397.             {pc += n2int($3);
  398.             }
  399.     |    opt_label OP_DSM expr
  400.             {int size = n2int($3);
  401.             if(size)
  402.             {    int align = 1;
  403.                  while(align < size)
  404.                  align <<= 1;
  405.                  pc += (align - (pc % align));
  406.             }
  407.             if($1)
  408.             {   sym_def($1, INT, pc);
  409.                  free($1);
  410.             }
  411.             pc += size;
  412.             }
  413.     |    OP_PAGE num ',' num ',' num ',' num
  414.             {if(pass == 2 && list_on) {
  415.                 sprintf(list_buf, "%s", spaces(0));
  416.             }}
  417.     |    OP_INCLUDE STRING
  418.             {if(pass == 2 && list_on) {
  419.                 printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
  420.                     spaces(0), luntab(cur_line));
  421.                 list_print_line = FALSE;
  422.             }
  423.             include($2); /* free($2); */
  424.             }
  425.     |    OP_END
  426.             {if(pass == 2 && list_on) {
  427.                 sprintf(list_buf, "%s", spaces(0));
  428.             }}
  429.     ;
  430.  
  431. dc_list
  432.     :    dc_list ',' dc_stuff
  433.     |    dc_stuff
  434.     ;
  435.  
  436. dc_stuff
  437.     :    STRING
  438.             {int len = strlen($1), i; char *cp; w0 = 0;
  439.             if(len % 3 == 2)
  440.                 len++;    /* force empty word */
  441.             for(i = 0, cp = $1; i < len; i++, cp++) {
  442.                 w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
  443.                 if(i % 3 == 2 || i == len - 1) {
  444.                     if(pass == 2) {
  445.                         if(list_on) sprintf(list_buf, "%c:%04X %06X%s",
  446.                             segs[seg], pc, w0, 
  447.                             spaces(14-6+5));
  448.                         gencode(seg, pc, w0);
  449.                     }
  450.                     pc++; w0 = 0;
  451.                 }
  452.             }
  453.             free($1);}
  454.      |    expr
  455.             {int frac = n2frac($1);
  456.             if(pass == 2) {
  457.                 if(list_on) {
  458.                     sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc, 
  459.                         frac & 0xFFFFFF, spaces(14-6+5));
  460.                 }
  461.                 gencode(seg, pc, frac);
  462.             }
  463.             pc++;}
  464.  
  465. space    :    PMEM
  466.             {$$ = PROG;}
  467.     |    XMEM
  468.             {$$ = XDATA;}
  469.     |    YMEM
  470.             {$$ = YDATA;}
  471.     |    LMEM
  472.             {$$ = LDATA;}
  473.     ;       
  474.  
  475. label_field
  476.     :    SYM
  477.             {sym_def($1, INT, pc);
  478.             free($1);}
  479.     |    /* empty */
  480.     ;
  481.  
  482. opt_label
  483.     :    SYM        {$$ = $1;}
  484.     |    /* empty */    {$$ = NULL;}
  485.     ;
  486.  
  487. operation_field
  488.     :    operation
  489.             {if(just_rep) 
  490.                 just_rep--;}
  491.     ;
  492.  
  493. operation
  494.     :    no_parallel
  495.     |    parallel_ok
  496.             {w0 |= 0x200000;}
  497.     |    parallel_ok parallel_move
  498.     ;
  499.  
  500. /*%%%************* instructions that allow parallel moves ****************/
  501.  
  502. parallel_ok
  503.     :
  504.         OP_MPY mpy_arg
  505.             {w0 |= 0x80 | $2 << 2;}
  506.     |    OP_MPYR mpy_arg
  507.             {w0 |= 0x81 | $2 << 2;}
  508.     |    OP_MAC mpy_arg
  509.             {w0 |= 0x82 | $2 << 2;}
  510.     |    OP_MACR mpy_arg
  511.             {w0 |= 0x83 | $2 << 2;}
  512.  
  513.     |       OP_SUB op8_1
  514.             {w0 |= 0x04 | $2 << 3;}
  515.     |    OP_ADD op8_1
  516.             {w0 |= 0x00 | $2 << 3;}
  517.     |    OP_MOVE
  518.             {w0 |= 0x00;}
  519.  
  520.     |    OP_TFR op8_2
  521.             {w0 |= 0x01 | $2 << 3;}
  522.     |    OP_CMP op8_2
  523.             {w0 |= 0x05 | $2 << 3;}
  524.     |    OP_CMPM op8_2
  525.             {w0 |= 0x07 | $2 << 3;}
  526.  
  527.     |    OP_RND op8_3
  528.             {w0 |= 0x11 | $2 << 3;}
  529.     |    OP_ADDL op8_3
  530.             {w0 |= 0x12 | $2 << 3;}
  531.     |    OP_CLR op8_3
  532.             {w0 |= 0x13 | $2 << 3;}
  533.     |    OP_SUBL op8_3
  534.             {w0 |= 0x16 | $2 << 3;}
  535.     |    OP_NOT op8_3
  536.             {w0 |= 0x17 | $2 << 3;}
  537.  
  538.     |    OP_ADDR op8_4
  539.             {w0 |= 0x02 | $2 << 3;}
  540.     |    OP_TST op8_4
  541.             {w0 |= 0x03 | $2 << 3;}
  542.     |    OP_SUBR op8_4
  543.             {w0 |= 0x06 | $2 << 3;}
  544.  
  545.     |       OP_AND op8_5
  546.             {w0 |= 0x46 | $2 << 3;}
  547.     |    OP_OR op8_5
  548.             {w0 |= 0x42 | $2 << 3;}
  549.     |       OP_EOR op8_5
  550.             {w0 |= 0x43 | $2 << 3;}
  551.  
  552.     |       OP_ASR op8_6
  553.             {w0 |= 0x22 | $2 << 3;}
  554.     |       OP_LSR op8_6
  555.             {w0 |= 0x23 | $2 << 3;}
  556.     |       OP_ABS op8_6
  557.             {w0 |= 0x26 | $2 << 3;}
  558.     |       OP_ROR op8_6
  559.             {w0 |= 0x27 | $2 << 3;}
  560.  
  561.     |       OP_ASL op8_7
  562.             {w0 |= 0x32 | $2 << 3;}
  563.     |       OP_LSL op8_7
  564.             {w0 |= 0x33 | $2 << 3;}
  565.     |       OP_NEG op8_7
  566.             {w0 |= 0x36 | $2 << 3;}
  567.     |       OP_ROL op8_7
  568.             {w0 |= 0x37 | $2 << 3;}
  569.  
  570.     |       OP_ADC op8_8
  571.             {w0 |= 0x21 | $2 << 3;}
  572.     |       OP_SBC op8_8
  573.             {w0 |= 0x25 | $2 << 3;}
  574.     ;
  575.  
  576. mpy_arg    :    plus_minus mpy_srcs ',' a_b
  577.             {$$ = $1 | $4 << 1 | $2 << 2;}
  578.     ;
  579.  
  580. plus_minus
  581.     :    '+'    
  582.             {$$ = 0;}
  583.     |    '-'    
  584.             {$$ = 1;}
  585.     |    
  586.             {$$ = 0;}
  587.     ;
  588.  
  589. mpy_srcs
  590.     :       XREG ',' XREG
  591.             {switch ($1 << 4 | $3) {
  592.                 case 0x00: $$ = 0x0; break;
  593.                 case 0x01: 
  594.                 case 0x10: $$ = 0x2; break;
  595.                 case 0x11: 
  596.                     yyerror("illegal source operands"); 
  597.                     break;
  598.             }}                  
  599.     |    YREG ',' YREG
  600.             {switch ($1 << 4 | $3) {
  601.                 case 0x00: $$ = 0x1; break;
  602.                 case 0x01: 
  603.                 case 0x10: $$ = 0x3; break;
  604.                 case 0x11: 
  605.                     yyerror("illegal source operands"); 
  606.                     break;
  607.             }}                  
  608.     |    XREG ',' YREG
  609.             {switch ($1 << 4 | $3) {
  610.                 case 0x00: $$ = 0x5; break;
  611.                 case 0x01: $$ = 0x4; break;
  612.                 case 0x10: $$ = 0x6; break;
  613.                 case 0x11: $$ = 0x7; break;
  614.             }}                  
  615.     |    YREG ',' XREG
  616.             {switch ($1 << 4 | $3) {
  617.                 case 0x00: $$ = 0x5; break;
  618.                 case 0x01: $$ = 0x6; break;
  619.                 case 0x10: $$ = 0x4; break;
  620.                 case 0x11: $$ = 0x7; break;
  621.             }}                  
  622.     ;
  623.  
  624. op8_1    :    BBBB ',' AAAA
  625.             {$$ = 0x2;}
  626.     |    AAAA ',' BBBB
  627.             {$$ = 0x3;}
  628.     |    XXXX ',' a_b
  629.             {$$ = 0x4 | $3;}
  630.     |    YYYY ',' a_b
  631.             {$$ = 0x6 | $3;}
  632.     |    XREG ',' a_b
  633.             {$$ = 0x8 | $1 << 2 | $3;}
  634.     |    YREG ',' a_b
  635.             {$$ = 0xA | $1 << 2 | $3;}
  636.     ;
  637.  
  638. op8_2    :    BBBB ',' AAAA
  639.             {$$ = 0x0;}
  640.     |    AAAA ',' BBBB
  641.             {$$ = 0x1;}
  642.     |    XREG ',' a_b
  643.             {$$ = 0x8 | $1 << 2 | $3;}
  644.     |    YREG ',' a_b
  645.             {$$ = 0xA | $1 << 2 | $3;}
  646.     ;
  647.  
  648. op8_3    :    AAAA
  649.             {$$ = 0x0;}
  650.     |    BBBB
  651.             {$$ = 0x1;}
  652.     |    BBBB ',' AAAA
  653.             {$$ = 0x0;}
  654.     |    AAAA ',' BBBB
  655.             {$$ = 0x1;}
  656.     ;
  657.  
  658. op8_4    :    op8_3
  659.             {$$ = $1;}
  660.     ;
  661.  
  662. op8_5    :    XREG ',' a_b
  663.             {$$ = 0x0 | $1 << 2 | $3;}
  664.     |    YREG ',' a_b
  665.             {$$ = 0x2 | $1 << 2 | $3;}
  666.     ;
  667.  
  668. op8_6    :    a_b
  669.             {$$ = $1;}
  670.     ;
  671.  
  672. op8_7    :    a_b
  673.             {$$ = $1;}
  674.     ;
  675.  
  676. op8_8    :    XXXX ',' a_b
  677.             {$$ = 0x0 | $3;}
  678.     |    YYYY ',' a_b
  679.             {$$ = 0x2 | $3;}
  680.     ;
  681.  
  682. a_b    :    AAAA
  683.             {$$ = 0;}
  684.     |    BBBB
  685.             {$$ = 1;}
  686.     ;
  687.  
  688. no_parallel
  689.     :    control_inst
  690.             {if(just_rep == 1)
  691.                 yyerror("instruction not allowed after REP");}
  692.     |    bit_inst
  693.     |    move_inst
  694.     |    arith_inst
  695.     ;
  696.  
  697. /*%%%************** non-parallel arithmetic and logical ********************/
  698.  
  699. arith_inst
  700.     :    OP_NORM RREG ',' a_b
  701.             {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
  702.     |    OP_DIV sd3
  703.             {w0 |= 0x018040 | $2 << 3;}
  704.     |    or_op ix ',' funky_ctl_reg
  705.             {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;}
  706.     |    and_op ix ',' funky_ctl_reg
  707.             {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;}
  708.     ;
  709.  
  710. or_op    :    OP_OR
  711.     |    OP_ORI
  712.     ;
  713.  
  714. and_op    :    OP_AND
  715.     |    OP_ANDI
  716.     ;
  717.  
  718. /*%%%******************************* control instructions **********************/
  719.  
  720. control_inst
  721.     :    OP_JSCC ea_a12
  722.             {if($2) {
  723.                 w0 |= 0x0BC0A0 | $1 << 0;
  724.             } else {
  725.                 w0 |= 0x0F0000 | $1 << 12;
  726.             }}
  727.     |    OP_JCC ea_a12
  728.             {if($2) {
  729.                 w0 |= 0x0AC0A0 | $1 << 0;
  730.             } else {
  731.                 w0 |= 0x0E0000 | $1 << 12;
  732.             }}
  733.     |    OP_JSR ea_a12
  734.             {if($2) {
  735.                 w0 |= 0x0BC080;
  736.             } else {
  737.                 w0 |= 0x0D0000;
  738.             }}
  739.     |    OP_JMP ea_a12
  740.             {if($2) {
  741.                 w0 |= 0x0AC080;
  742.             } else {
  743.                 w0 |= 0x0C0000;
  744.             }}
  745.  
  746.     |    OP_JSSET control_args
  747.             {w0 |= 0x0B0020;}
  748.     |    OP_JSCLR control_args
  749.             {w0 |= 0x0B0000;}
  750.     |    OP_JSET control_args
  751.             {w0 |= 0x0A0020;}
  752.     |    OP_JCLR control_args
  753.             {w0 |= 0x0A0000;}
  754.  
  755.     |    OP_REP rep_args
  756.             {just_rep = 2;}
  757.     |    OP_DO do_args
  758.             {uses_w1++;}
  759.     |    OP_ENDDO
  760.             {w0 |= 0x00008C;}
  761.     |    OP_STOP
  762.             {w0 |= 0x000087;}
  763.     |    OP_WAIT
  764.             {w0 |= 0x000086;}
  765.     |    OP_RESET
  766.             {w0 |= 0x000084;}
  767.     |    OP_RTS
  768.             {w0 |= 0x00000C;}
  769.     |    OP_SWI
  770.             {w0 |= 0x000006;}
  771.     |    OP_ILLEGAL
  772.             {w0 |= 0x000005;}
  773.     |    OP_RTI
  774.             {w0 |= 0x000004;}
  775.     |    OP_NOP
  776.             {w0 |= 0x000000;
  777.             just_rep = 0;}
  778.     ;
  779.  
  780. do_args    :    ix ',' abs_addr
  781.             {int ival = n2int($1);
  782.             w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
  783.             if(ival > 0xFFF && pass == 2) {
  784.                 yyerror("warning: immediate operand truncated");
  785.             }
  786.             w1 |= $3-1;}
  787.     |    regs ',' abs_addr
  788.             {w0 |= 0x06C000 | $1.r6 << 8;
  789.             w1 |= $3-1;}
  790.     |    x_or_y ea_no_ext ',' abs_addr
  791.             {w0 |= 0x064000 | $2 << 8 | $1 << 6;
  792.             w1 |= $4-1;}
  793.     |    x_or_y abs_short_addr ',' abs_addr    /* allow forced */
  794.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  795.             if($2 > 0x003F && pass == 2)
  796.                 yyerror("warning: address operand truncated");
  797.             w1 |= $4-1;}
  798.     |    x_or_y abs_addr ',' abs_addr
  799.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  800.             if($2 > 0x003F && pass == 2)
  801.                 yyerror("warning: address operand truncated");
  802.             w1 |= $4-1;}
  803.     ;               
  804.  
  805. rep_args
  806.     :    ix
  807.             {int ival = n2int($1);
  808.             w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
  809.             if(ival > 0xFFF && pass == 2) {
  810.                 yyerror("warning: immediate operand truncated");
  811.             }}
  812.     |    regs
  813.             {w0 |= 0x06C020 | $1.r6 << 8;}
  814.     |    x_or_y ea_no_ext
  815.             {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
  816.     |    x_or_y abs_addr
  817.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  818.             if($2 > 0x003F && pass == 2)
  819.                 yyerror("warning: address operand truncated");
  820.             }
  821.     |    x_or_y abs_short_addr    /* forced */
  822.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  823.             if($2 > 0x003F && pass == 2)
  824.                 yyerror("warning: address operand truncated");
  825.             }
  826.     ;
  827.  
  828. control_args
  829.     :    b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
  830.             {w0 |= $1 << 0 | $3 << 6;
  831.             uses_w1++;
  832.             w1 = $6;}
  833.     |    b5_10111_max ',' regs ',' abs_addr
  834.             {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
  835.             uses_w1++;
  836.             w1 = $5;}
  837.     ;
  838.  
  839. p6_ean_a6
  840.     :    abs_addr    /* in pass 2 can always discern size. */
  841.                 /* Sometimes in pass one, too.  But since */
  842.                 /* address extension is always used for the */
  843.                 /* branch target, pass 1 can assume the */
  844.                 /* symbol value will fit; warning in pass 2 */
  845.                 /* if it doesn't */
  846.             {if($1 != -1) {    /* symbol defined */
  847.                 w0 |= ($1 & 0x3F) << 8;
  848.                 if($1 >= 0xFFC0) {
  849.                     w0 |= 0x008080;
  850.                 } else {
  851.                     w0 |= 0x000080;
  852.                     if($1 > 0x003F && pass == 2)
  853.                         yyerror("warning: address operand truncated");
  854.                 }
  855.             }}
  856.     |    abs_short_addr
  857.             {if($1 != -1) {
  858.                 if($1 > 0x3F && pass == 2)
  859.                     yyerror("warning: address operand truncated");
  860.                 w0 |= 0x000080 | ($1 & 0x3F) << 8;
  861.             }}
  862.     |    io_short_addr
  863.             {if($1 != -1) {
  864.                 if($1 < 0xFFC0 && pass == 2)
  865.                     yyerror("warning: address operand truncated");
  866.                 w0 |= 0x008080 | ($1 & 0x3F) << 8;
  867.             }}
  868.     |    ea_no_ext
  869.             {w0 |= 0x004080 | $1 << 8;}
  870.     ;
  871.  
  872. /*%%%**************************** bit instructions ***************************/
  873.  
  874. bit_inst
  875.     :    OP_BTST bit_args
  876.             {w0 |= 0x0B0020;}
  877.     |    OP_BCHG bit_args
  878.             {w0 |= 0x0B0000;}
  879.     |    OP_BSET bit_args
  880.             {w0 |= 0x0A0020;}
  881.     |    OP_BCLR bit_args
  882.             {w0 |= 0x0A0000;}
  883.     ;               
  884.  
  885. bit_args
  886.     :    b5_10111_max ',' x_or_y p6_ea_a6
  887.             {w0 |= $1 << 0 | $3 << 6;}
  888.     |    b5_10111_max ',' regs
  889.             {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
  890.     ;           
  891.  
  892. p6_ea_a6
  893.     :    io_short_addr    /* must be forced to tell from abs_addr */
  894.             {if($1 != -1) {
  895.                 w0 |= ($1 & 0x3F) << 8 | 0x008000;
  896.                 if($1 < 0xFFC0 && pass == 2)
  897.                     yyerror("warning: address operand truncated");
  898.             }}
  899.     |    abs_short_addr    /* must be forced to tell from abs_addr */
  900.             {if($1 != -1) {
  901.                 w0 |= ($1 & 0x3F) << 8 | 0x000000;
  902.                 if($1 > 0x003F && pass == 2)
  903.                     yyerror("warning: address operand truncated");
  904.             }}
  905.     |    ea    /* can use abs_addr */
  906.             {w0 |= 0x004000;}
  907.     ;
  908.  
  909. /*%%%************************** move instructions **********************/
  910.  
  911. move_inst
  912.     :    OP_MOVEP movep_args
  913.     |    OP_MOVEM movem_args
  914.     |    OP_MOVEC movec_args
  915.     |    OP_LUA ea_short ',' regs
  916.             {w0 |= 0x044010 | $2 << 8 | $4.r4;}
  917.     |    OP_TCC tcc_args
  918.             {w0 |= $1 << 12;}
  919.     ;           
  920.  
  921. tcc_args
  922.     :    tcc_sd
  923.             {w0 |= 0x020000 | $1 << 3;}
  924.     |    tcc_sd RREG ',' RREG
  925.             {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
  926.     ;
  927.  
  928. tcc_sd    :    regs /* a_b */ ',' regs /* a_b */
  929.             {if($1.flags & R_AB && $3.flags & R_AB) {
  930.                 if($1.ab == $3.ab) 
  931.                     yyerror("source and dest must be different");
  932.                 $$ = $3.ab;
  933.             } else if($1.flags & R_XREG && $3.flags & R_AB) {
  934.                 $$ = 0x8 | $1.xreg << 2 | $3.ab;
  935.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  936.                 $$ = 0xA | $1.yreg << 2 | $3.ab;
  937.             } else 
  938.                 yyerror("illegal TCC operands");
  939.             }
  940.     ;
  941.  
  942. sd3    :    regs /* XREG */ ',' regs /* a_b */
  943.             {if($1.flags & R_XREG && $3.flags & R_AB) {
  944.                 $$ = $1.xreg << 2 | $3.ab;
  945.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  946.                 $$ = $1.yreg << 2 | 2 | $3.ab;
  947.             }}
  948.     ;
  949.  
  950. movec_args
  951.     :    x_or_y ea ',' regs /* ctl_reg */
  952.             {if(NOT ($4.flags & R_CTL_REG))
  953.                 yyerror("bad MOVEC target register");
  954.             if($1 == 0) {
  955.                 w0 |= 0x05C020 | $4.ctl_reg;
  956.             } else {
  957.                 w0 |= 0x05C060 | $4.ctl_reg;
  958.             }}
  959.     |    regs /* ctl_reg */ ',' x_or_y ea
  960.             {if(NOT ($1.flags & R_CTL_REG))
  961.                 yyerror("bad MOVEC source register");
  962.             if($3 == 0) {
  963.                 w0 |= 0x054020 | $1.ctl_reg;
  964.             } else {
  965.                 w0 |= 0x054060 | $1.ctl_reg;
  966.             }}
  967.     |    ix ',' regs /* ctl_reg */
  968.             {int ival = n2int($1);
  969.             if(NOT ($3.flags & R_CTL_REG))
  970.                 yyerror("bad MOVEC target register");
  971.             if(ival < 256 && NOT long_symbolic_expr) {
  972.                 w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; 
  973.             } else {
  974.                 w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
  975.                 uses_w1++; w1 = ival & 0xFFFF;
  976.             }}
  977.     |    x_or_y abs_short_addr ',' regs /* ctl_reg */
  978.             {if($1 == 0) {
  979.                 w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  980.             } else {
  981.                 w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  982.             }
  983.             if(NOT ($4.flags & R_CTL_REG))
  984.                 yyerror("bad MOVEC target register");
  985.             if($2 > 0x003F && pass == 2)
  986.                 yyerror("warning: address operand truncated");
  987.             }
  988.     |    regs /* ctl_reg */ ',' x_or_y abs_short_addr
  989.             {if($3 == 0) {
  990.                 w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  991.             } else {
  992.                 w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  993.             }
  994.             if(NOT ($1.flags & R_CTL_REG))
  995.                 yyerror("bad MOVEC source register");
  996.             if($4 > 0x003F && pass == 2)
  997.                 yyerror("warning: address operand truncated");
  998.             }
  999.     |    regs /* ctl_reg */ ',' regs
  1000.             {if($1.flags & R_CTL_REG) {
  1001.                 w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
  1002.             } else if($3.flags & R_CTL_REG) {
  1003.                 w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
  1004.             } else if($1.flags & $3.flags & R_CTL_REG) {
  1005.                 /* bogus? $$$ */
  1006.                        w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | 
  1007.                 $3.ctl_reg;
  1008.             } else {
  1009.                 yyerror("MOVEC must reference a control reg");
  1010.             }}
  1011.     ;
  1012.  
  1013. movep_args
  1014.     :    x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
  1015.             {w0 |= 0x084080;
  1016.             switch($2.pp << 1 | $5.pp) {
  1017.                 case 0:    case 3:
  1018.                     yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
  1019.                     break;
  1020.                 case 1:    /* ea, pp */
  1021.                     w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
  1022.                         ($5.ext & 0x3F);
  1023.                     if($2.mode == 0x003000) {
  1024.                         w0 |= 0x003000;
  1025.                         uses_w1++;
  1026.                         w1 = $2.ext;
  1027.                     } else {
  1028.                         w0 |= $2.mode;
  1029.                     }
  1030.                     break;
  1031.                 case 2:    /* pp, ea */
  1032.                     w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
  1033.                         ($2.ext & 0x3F);
  1034.                     if($5.mode == 0x003000) {
  1035.                         w0 |= 0x003000;
  1036.                         uses_w1++;
  1037.                         w1 = $5.ext;
  1038.                     } else {
  1039.                         w0 |= $5.mode;
  1040.                     }
  1041.                     break;
  1042.             }}
  1043.     |    ix ',' x_or_y num_or_sym
  1044.             {w0 |= 0x084080;
  1045.             w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | 
  1046.                 (n2int($4) & 0x3F);
  1047.             uses_w1++;
  1048.             w1 = n2int($1);}
  1049.     |    PMEM ea ',' x_or_y num_or_sym
  1050.             {w0 |= 0x084040;
  1051.             w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);}
  1052.     |    x_or_y movep_ea_pp ',' PMEM ea
  1053.             {w0 |= 0x084040;
  1054.             if($2.mode != 0x003000 && $2.mode != 0)
  1055.                 yyerror("illegal MOVEP");
  1056.             w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
  1057.     |    regs ',' x_or_y num_or_sym
  1058.             {w0 |= 0x084000;
  1059.             w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | 
  1060.                 (n2int($4) & 0x3F);}
  1061.     |    x_or_y movep_ea_pp ',' regs
  1062.             {w0 |= 0x084000;
  1063.             if(!$2.pp)
  1064.                 yyerror("illegal MOVEP");
  1065.             w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
  1066.     ;
  1067.  
  1068. movep_ea_pp
  1069.     :    abs_addr
  1070.             {if($1 != UNDEF && $1 >= 0xFFC0) {
  1071.                 /* defined symbol or constant, in i/o range */
  1072.                 $$.pp = 1;
  1073.                 $$.mode = 0;
  1074.             } else {
  1075.                 /* either out of i/o range or symbol not */
  1076.                 /* yet defined:  assume ea extension */
  1077.                 $$.pp = 0;
  1078.                 $$.mode = 0x003000;
  1079.             }
  1080.             $$.ext = $1;}
  1081.     |    io_short_addr    /* forced i/o short */
  1082.             {$$.pp = 1;
  1083.             $$.mode = 0;
  1084.             if($1 < 0xFFC0 && pass == 2)
  1085.                 yyerror("warning: address operand truncated");
  1086.             $$.ext = $1;}
  1087.     |    ea_no_ext
  1088.             {$$.pp = 0;
  1089.             $$.mode = $1 << 8;
  1090.             $$.ext = $1;}
  1091.     ;
  1092.  
  1093. movem_args
  1094.     :    regs ',' PMEM ea_a6
  1095.             {w0 |= 0x070000 | 0 << 15 | $1.r6;}
  1096.     |    PMEM ea_a6 ',' regs
  1097.             {w0 |= 0x070000 | 1 << 15 | $4.r6;}
  1098.     ;
  1099.  
  1100. /*%%%**************** memory reference fields ************************/
  1101.  
  1102. b5_10111_max
  1103.     :    ix
  1104.             {int ival = n2int($1);
  1105.             $$ = ival; if(ival > 0x17) 
  1106.                 yyerror("%d: illegal bit number", ival);}
  1107.     ;
  1108.  
  1109. x_or_y    :    XMEM
  1110.             {$$ = 0;}
  1111.     |    YMEM
  1112.             {$$ = 1;}
  1113.     ;
  1114.  
  1115. /*%%%**************** effective address fields ************************/
  1116.  
  1117. ea_a6    :    ea
  1118.             {w0 |= 0x004080;}
  1119.     |    abs_short_addr
  1120.             {w0 |= ($1 & 0x3F) << 8;
  1121.             if($1 > 0x003F && pass == 2)
  1122.                 yyerror("warning: address operand truncated");
  1123.             }
  1124.     ;
  1125.  
  1126. ea_a12    :    ea
  1127.             {$$ = 1;}
  1128.     |    abs_short_addr
  1129.             {w0 |= $1 & 0xFFF; $$ = 0;
  1130.             if($1 > 0x0FFF && pass == 2)
  1131.                 yyerror("warning: address operand truncated");
  1132.             }
  1133.     ;
  1134.  
  1135. ea    :    abs_addr
  1136.             {w0 |= 0x003000;
  1137.             uses_w1++;
  1138.             w1 |= $1;
  1139.             $$ = 0x003000;}
  1140.     |    ea_no_ext
  1141.             {w0 |= $1 << 8;
  1142.             $$ = $1 << 8;}
  1143.     ;
  1144.  
  1145. ea_no_ext
  1146.     :    ea_short
  1147.             {$$ = $1;}
  1148.     |    '(' RREG ')'
  1149.             {$$ = 4 << 3 | $2;}
  1150.     |    '(' RREG '+' NREG ')'
  1151.             {$$ = 5 << 3 | $2;
  1152.             if($2 != $4) yyerror("Rn and Nn must be same number");}
  1153.     |    '-' '(' RREG ')'
  1154.             {$$ = 7 << 3 | $3;}
  1155.     ;
  1156.  
  1157. ea_short
  1158.     :    '(' RREG ')' '-' NREG
  1159.             {$$ = 0 << 3 | $2;
  1160.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1161.     |    '(' RREG ')' '+' NREG
  1162.             {$$ = 1 << 3 | $2;
  1163.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1164.     |    '(' RREG ')' '-'
  1165.             {$$ = 2 << 3 | $2;}
  1166.     |    '(' RREG ')' '+'
  1167.             {$$ = 3 << 3 | $2;}
  1168.     ;
  1169.  
  1170. /*%%%******************* register fields ******************************/
  1171.  
  1172. regs    :    XREG
  1173.             {$$.r6 = $$.r5 = 0x04 | $1;
  1174.             $$.sdx = $1;
  1175.             $$.xreg = $1;
  1176.             $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;}
  1177.     |    YREG
  1178.             {$$.r6 = $$.r5 = 0x06 | $1;
  1179.             $$.sdy = $1;
  1180.             $$.yreg = $1;
  1181.             $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;}
  1182.     |    AREG
  1183.             {switch($1) {
  1184.                 case 0: 
  1185.                     $$.r6 = $$.r5 = 0x08 | 0; 
  1186.                     break;
  1187.                 case 1: 
  1188.                     $$.r6 = $$.r5 = 0x08 | 4; 
  1189.                     break;
  1190.                 case 2: 
  1191.                     $$.r6 = $$.r5 = 0x08 | 2; 
  1192.                     break;
  1193.             }
  1194.             $$.flags = R_R6|R_R5|R_UINT;}
  1195.     |    BREG
  1196.             {switch($1) {
  1197.                 case 0: 
  1198.                     $$.r6 = $$.r5 = 0x08 | 1; break;
  1199.                 case 1: 
  1200.                     $$.r6 = $$.r5 = 0x08 | 5; break;
  1201.                 case 2: 
  1202.                     $$.r6 = $$.r5 = 0x08 | 3; break;
  1203.             }
  1204.             $$.flags = R_R6|R_R5|R_UINT;}
  1205.     |    AAAA
  1206.             {$$.r6 = $$.r5 = 0x0E;
  1207.             $$.sdx = $$.sdy = 0x2;
  1208.             $$.ab = 0;
  1209.             $$.lsd = 4;
  1210.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
  1211.     |    BBBB
  1212.             {$$.r6 = $$.r5 = 0x0F;
  1213.             $$.sdx = $$.sdy = 0x3;
  1214.             $$.ab = 1;
  1215.             $$.lsd = 5;
  1216.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
  1217.     |    RREG
  1218.             {$$.r6 = $$.r5 = 0x10 | $1;
  1219.             $$.r4 = 0x00 | $1;
  1220.             $$.flags = R_R6|R_R5|R_R4|R_UINT;}
  1221.     |    NREG
  1222.             {$$.r6 = $$.r5 = 0x18 | $1;
  1223.             $$.r4 = 0x08 | $1;
  1224.             $$.flags = R_R6|R_R5|R_R4|R_UINT;}
  1225.     |    MREG
  1226.             {$$.r6 = 0x20 | $1;
  1227.             $$.r5 = -1;
  1228.             $$.ctl_reg = $1;
  1229.             $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
  1230.     |    prog_ctl_reg
  1231.             {$$.r6 = 0x38 | $1;
  1232.             $$.r5 = -1;
  1233.             $$.ctl_reg = 0x18 | $1;
  1234.             $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
  1235.     |    A10
  1236.             {$$.lsd  = 0;
  1237.             $$.flags = R_LSD;}
  1238.     |    B10
  1239.             {$$.lsd = 1;
  1240.             $$.flags = R_LSD;}
  1241.     |    XXXX
  1242.             {$$.lsd = 2;
  1243.             $$.flags = R_LSD;}
  1244.     |    YYYY
  1245.             {$$.lsd = 3;
  1246.             $$.flags = R_LSD;}
  1247.     |    AABB
  1248.             {$$.lsd = 6;
  1249.             $$.flags = R_LSD;}
  1250.     |    BBAA
  1251.             {$$.lsd = 7;
  1252.             $$.flags = R_LSD;}
  1253.     ;
  1254.  
  1255. prog_ctl_reg
  1256.     :    SR
  1257.             {$$ = 1;}
  1258.     |    OMR
  1259.             {$$ = 2;}
  1260.     |    SP
  1261.             {$$ = 3;}
  1262.     |    SSH
  1263.             {$$ = 4;}
  1264.     |    SSL
  1265.             {$$ = 5;}
  1266.     |    LA
  1267.             {$$ = 6;}
  1268.     |    LC
  1269.             {$$ = 7;}
  1270.     ;
  1271.  
  1272. funky_ctl_reg
  1273.     :    MR
  1274.             {$$ = 0;}
  1275.     |    CCR
  1276.             {$$ = 1;}
  1277.     |    OMR
  1278.             {$$ = 2;}
  1279.     ;
  1280.  
  1281. /*%%%************************* parallel moves *************/
  1282.  
  1283. parallel_move
  1284.     :    i_move
  1285.     |    u_move
  1286.     |    x_or_y_move
  1287.     |    xr_move
  1288.     |    ry_move
  1289.     |    r_move
  1290.     |    xy_move
  1291.     |    l_move
  1292.     ;
  1293.  
  1294. i_move  :    ix ',' regs
  1295.             {int ival = n2int($1);
  1296.             int frac = n2frac($1);
  1297.             int value;
  1298.             BOOL shortform = FALSE;
  1299.             if($3.flags & R_CTL_REG) {
  1300.                 yyerror("please use MOVEC for control register moves");
  1301.                 break;
  1302.             }
  1303.             if(($3.flags & R_SFRAC) && $1.type == FLT) {
  1304.                 if((frac & 0xFFFF) == 0 && 
  1305.                     NOT long_symbolic_expr) {
  1306.                     value = frac >> 16;
  1307.                     shortform++;
  1308.                 } else {
  1309.                     value = frac;
  1310.                 }
  1311.             } else {
  1312.                 if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) {
  1313.                     value = ival;
  1314.                     shortform++;
  1315.                 } else {
  1316.                     value = ival;
  1317.                 }
  1318.             }
  1319.  
  1320.             if(shortform) {
  1321.                 w0 |= 0x200000 | (value & 0xFF) << 8 |
  1322.                     $3.r5 << 16;
  1323.             } else {
  1324.                 w0 |= 0x400000 | 0x00F400 |
  1325.                     ($3.r5 >> 3 & 3) << 20 | 
  1326.                     ($3.r5 & 7) << 16;
  1327.                 uses_w1++; w1 = value;
  1328.             }}
  1329.     ;
  1330.  
  1331. r_move    :    regs ',' regs
  1332.             {
  1333.                 if($3.flags & R_CTL_REG) {
  1334.                     yyerror("please use MOVEC for control register moves");
  1335.                     break;
  1336.                 }
  1337.                 if($1.flags & R_R5 & $3.flags) 
  1338.                     w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
  1339.                 else
  1340.                     yyerror("illegal R move");
  1341.             }    
  1342.     ;
  1343.  
  1344. u_move    :    ea_short
  1345.             {w0 |= 0x204000 | $1 << 8;}
  1346.     ;
  1347.  
  1348. x_or_y_move
  1349.     :    x_or_y ea ',' regs
  1350.             {w0 |= 0x40C000 | $1 << 19;
  1351.             if($4.flags & R_CTL_REG) {
  1352.                 yyerror("please use MOVEC for control register moves");
  1353.                 break;
  1354.             }
  1355.             w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1356.     |    x_or_y abs_short_addr ',' regs
  1357.             {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
  1358.             if($4.flags & R_CTL_REG) {
  1359.                 yyerror("please use MOVEC for control register moves");
  1360.                 break;
  1361.             }
  1362.             if($2 > 0x003F && pass == 2)
  1363.                 yyerror("warning: address operand truncated");
  1364.             w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1365.     |    regs ',' x_or_y ea
  1366.             {w0 |= 0x404000 | $3 << 19;
  1367.             if($1.flags & R_CTL_REG) {
  1368.                 yyerror("please use MOVEC for control register moves");
  1369.                 break;
  1370.             }
  1371.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1372.     |    regs ',' x_or_y abs_short_addr
  1373.             {w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
  1374.             if($1.flags & R_CTL_REG) {
  1375.                 yyerror("please use MOVEC for control register moves");
  1376.                 break;
  1377.             }
  1378.             if($4 > 0x003F && pass == 2)
  1379.                 yyerror("warning: address operand truncated");
  1380.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1381.     |    ix_long ',' regs
  1382.             {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
  1383.                 ($3.r5 & 7) << 16;
  1384.             if($3.flags & R_CTL_REG) {
  1385.                 yyerror("please use MOVEC for control register moves");
  1386.                 break;
  1387.             }
  1388.             uses_w1++; w1 = n2frac($1);
  1389.             }
  1390.     ;
  1391.  
  1392. xr_move    :    x_or_y /* XMEM */ ea ',' regs    regs /* a_b */ ',' YREG
  1393.             {if($1 == 0 && $5.flags & R_AB) {
  1394.                 w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
  1395.                     $7 << 16;
  1396.             } else {
  1397.                 yyerror("illegal X:R move");
  1398.             }}
  1399.     |     ix ',' regs        regs /* a_b */ ',' YREG
  1400.             {if($4.flags & R_AB) {
  1401.                 w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
  1402.                     $6 << 16;
  1403.                 uses_w1++;
  1404.                 w1 |= n2frac($1) & 0xFFFFFF;
  1405.             } else {
  1406.                 yyerror("illegal X:R move");
  1407.             }}
  1408.     |    regs ',' x_or_y /* XMEM */ ea    regs /* a_b */ ',' regs/*YREG*/
  1409.             {if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
  1410.                 $7.flags & R_YREG) {
  1411.                 w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
  1412.                     $7.yreg << 16;
  1413.             } else if($1.flags & R_AB && $3 == 0 && 
  1414.                 $5.flags & R_XREG && $7.flags & R_AB) {
  1415.                 if($5.xreg != 0) yyerror("must use X0");
  1416.                 if($1.ab == 0 && $7.ab == 0)
  1417.                     w0 |= 0x080000;
  1418.                 else if($1.ab == 1 && $7.ab == 1)
  1419.                     w0 |= 0x090000;
  1420.                 else
  1421.                     yyerror("illegal X:R move");
  1422.             } else {
  1423.                 yyerror("illegal X:R move");
  1424.             }}
  1425.     ;
  1426.  
  1427. ry_move    :    regs /* a_b */ ',' regs /* XREG    */      YMEM ea ',' regs
  1428.             {if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
  1429.                 w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 |
  1430.                     $7.sdy << 16;
  1431.             } else {
  1432.                 yyerror("illegal R:Y move");
  1433.             }}
  1434.     |    regs /* a_b */ ',' regs /* XREG    */    ix ',' regs
  1435.             {if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
  1436.                 w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
  1437.                     $6.sdy << 16;
  1438.                 uses_w1++;
  1439.                 w1 |= n2frac($4) & 0xFFFFFF;
  1440.             } else {
  1441.                 yyerror("illegal R:Y move");
  1442.             }}
  1443.     |    regs /* a_b */ ',' regs /* XREG    */    regs ',' YMEM ea
  1444.             {if($1.flags & R_AB && $3.flags & R_XREG) {
  1445.                 w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
  1446.                 $4.sdy << 16;
  1447.             } else if ($1.flags & R_YREG && $3.flags & R_AB &&
  1448.                 $4.flags & R_AB) {
  1449.                 if($1.yreg != 0) yyerror("must use Y0");
  1450.                 if($3.ab == 0 && $4.ab == 0)
  1451.                     w0 |= 0x088000;
  1452.                 else if($3.ab == 1 && $4.ab == 1)
  1453.                     w0 |= 0x098000;
  1454.                 else
  1455.                     yyerror("illegal R:Y move");
  1456.             } else {
  1457.                 yyerror("illegal R:Y move");
  1458.             }}
  1459.     ;
  1460.  
  1461. l_move    :    LMEM ea ',' regs /* lsd */
  1462.             {if($4.flags & R_CTL_REG) {
  1463.                 yyerror("please use MOVEC for control register moves");
  1464.                 break;
  1465.             }
  1466.             w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
  1467.     |    regs /* lsd */ ',' LMEM ea
  1468.             {if($1.flags & R_CTL_REG) {
  1469.                 yyerror("please use MOVEC for control register moves");
  1470.                 break;
  1471.             }
  1472.             w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
  1473.     |    LMEM abs_short_addr ',' regs /* lsd */
  1474.             {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
  1475.             if($4.flags & R_CTL_REG) {
  1476.                 yyerror("please use MOVEC for control register moves");
  1477.                 break;
  1478.             }
  1479.             if($2 > 0x003F && pass == 2)
  1480.                 yyerror("warning: address operand truncated");
  1481.             w0 |= ($2 & 0x3F) << 8;}
  1482.     |    regs /* lsd */ ',' LMEM abs_short_addr
  1483.             {w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
  1484.             if($1.flags & R_CTL_REG) {
  1485.                 yyerror("please use MOVEC for control register moves");
  1486.                 break;
  1487.             }
  1488.             if($4 > 0x003F && pass == 2)
  1489.                 yyerror("warning: address operand truncated");
  1490.             w0 |= ($4 & 0x3F) << 8;}
  1491.     ;
  1492.  
  1493. xy_move    :    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    YMEM ea /*ea_strange*/ ',' regs
  1494.             {int eax = $2, eay = $6,
  1495.                  regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
  1496.                  regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
  1497.             if((eax & 0x400) == (eay & 0x400))
  1498.                 yyerror("registers must be in opposite halves");
  1499.             if(!($4.flags & (R_AB | R_XREG)))
  1500.                 yyerror("invalid X move register");
  1501.             if(!($8.flags & (R_AB | R_YREG)))
  1502.                 yyerror("invalid Y move register");
  1503.             if($4.flags & R_AB &&
  1504.                $8.flags & R_AB &&
  1505.                $4.ab == $8.ab)
  1506.                 yyerror("duplicate destination register");
  1507.             w0 = w0 & 0xFF | 0xC08000;    /* both write */
  1508.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1509.     |    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    regs ',' YMEM ea /*ea_strange*/
  1510.             {int eax = $2, eay = $8,
  1511.                  regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
  1512.                  regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
  1513.             if((eax & 0x400) == (eay & 0x400))
  1514.                 yyerror("registers must be in opposite halves");
  1515.             if(!($4.flags & (R_AB | R_XREG)))
  1516.                 yyerror("invalid X move register");
  1517.             if(!($5.flags & (R_AB | R_YREG)))
  1518.                 yyerror("invalid Y move register");
  1519.             w0 = w0 & 0xFF | 0x808000;    /* X:write, Y:read */
  1520.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1521.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    YMEM ea /*ea_strange*/ ',' regs
  1522.             {int eax = $4, eay = $6,
  1523.                  regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
  1524.                  regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
  1525.             if((eax & 0x400) == (eay & 0x400))
  1526.                 yyerror("registers must be in opposite halves");
  1527.             if(!($1.flags & (R_AB | R_XREG)))
  1528.                 yyerror("invalid X move register");
  1529.             if(!($8.flags & (R_AB | R_YREG)))
  1530.                 yyerror("invalid Y move register");
  1531.                   w0 = w0 & 0xFF | 0xC00000;    /* X:read, Y:write */
  1532.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1533.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    regs ',' YMEM ea /*ea_strange*/
  1534.             {int eax = $4, eay = $8,
  1535.                  regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
  1536.                  regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
  1537.             if((eax & 0x400) == (eay & 0x400))
  1538.                 yyerror("registers must be in opposite halves");
  1539.             if(!($1.flags & (R_AB | R_XREG)))
  1540.                 yyerror("invalid X move register");
  1541.             if(!($5.flags & (R_AB | R_YREG)))
  1542.                 yyerror("invalid Y move register");
  1543.                   w0 = w0 & 0xFF | 0x800000;    /* both read */
  1544.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1545.     ;
  1546.  
  1547. /*%%%******* absolute address and immediate data fields ************/
  1548.  
  1549. num    :    CHEX
  1550.             {$$ = $1;}
  1551.     |    CDEC
  1552.             {$$ = $1;}
  1553.     |    FRAC
  1554.             {$$ = $1;}
  1555.     ;
  1556.  
  1557. ix    :    '#' expr
  1558.             {$$ = $2;}
  1559.     |    '#' '<' expr
  1560.             {$$.val.i = n2int($3) & 0xFF;
  1561.             $$.type = INT;
  1562.             long_symbolic_expr = FALSE;}
  1563.     ;
  1564.  
  1565. ix_long    :    '#' '>' expr
  1566.             {$$ = $3;}
  1567.     ;
  1568.  
  1569. abs_addr
  1570.     :    expr
  1571.             {$$ = n2int($1);}
  1572.     ;
  1573.  
  1574. abs_short_addr
  1575.     :    '<' expr
  1576.             {$$ = n2int($2);}
  1577.     ;
  1578.  
  1579. io_short_addr
  1580.     :    SHL expr
  1581.             {$$ = n2int($2);} 
  1582.     ;
  1583.  
  1584. num_or_sym
  1585.     :    num
  1586.             {$$ = $1;}
  1587.     |    SYM
  1588.             {$$ = sym_ref($1); free($1);}
  1589.     |    io_short_addr
  1590.             {$$.type = INT; $$.val.i = $1;}
  1591.     ;
  1592.  
  1593. num_or_sym_expr
  1594.     :    num
  1595.             {$$ = $1;}
  1596.     |    SYM
  1597.             {$$ = sym_ref($1); free($1); long_symbolic_expr++;}
  1598.     |    CHAR
  1599.             {$$.type = INT; $$.val.i = $1 & 0xFFFFFF;}
  1600.     |    '*'
  1601.             {$$.type = INT; $$.val.i = pc;}
  1602.     ;
  1603.  
  1604. expr
  1605.     :    OP_INT '(' expr ')'
  1606.             {$$.type = INT; 
  1607.                 if($3.type == INT)
  1608.                     $$.val.i = $3.val.i;
  1609.                 else
  1610.                     $$.val.i = $3.val.f;
  1611.             }
  1612.     |    expr '|' expr
  1613.             {$$ = binary_op($1, '|', $3);}
  1614.     |    expr '^' expr
  1615.             {$$ = binary_op($1, '^', $3);}
  1616.     |    expr '&' expr
  1617.             {$$ = binary_op($1, '&', $3);}
  1618.     |    expr SHR expr
  1619.             {$$ = binary_op($1, SHR, $3);}
  1620.     |    expr SHL expr
  1621.             {$$ = binary_op($1, SHL, $3);}
  1622.     |    expr '-' expr
  1623.             {$$ = binary_op($1, '-', $3);}
  1624.     |    expr '+' expr
  1625.             {$$ = binary_op($1, '+', $3);}
  1626.     |    expr '%' expr
  1627.             {$$ = binary_op($1, '%', $3);}
  1628.     |    expr '/' expr
  1629.             {$$ = binary_op($1, '/', $3);}
  1630.     |    expr '*' expr
  1631.             {$$ = binary_op($1, '*', $3);}
  1632.     |    '-' expr %prec '~'
  1633.             {$$ = unary_op('-', $2);}
  1634.     |    '~' expr
  1635.             {$$ = unary_op('~', $2);}
  1636.     |    '(' expr ')'
  1637.             {$$ = $2;}
  1638.     |    num_or_sym_expr
  1639.             {$$ = $1;}
  1640.     ;
  1641.  
  1642. /*%%%****************** end ******************************/
  1643.  
  1644. %%
  1645.  
  1646. #include <stdio.h>
  1647.  
  1648. int yydebug;
  1649.  
  1650. struct n binary_op(a1, op, a2)
  1651. struct n a1, a2;
  1652. int op;
  1653. {
  1654.     struct n result;
  1655.  
  1656.     if(a1.type == UNDEF || a2.type == UNDEF) {
  1657.         result.type = UNDEF;
  1658.         return result;
  1659.     }
  1660.  
  1661.     /* promote to float automatically */
  1662.  
  1663.     if(a1.type != a2.type) {
  1664.         if(a1.type == INT) {
  1665.             a1.val.f = a1.val.i;        /* truncate */
  1666.             a1.type = FLT;
  1667.         } else {
  1668.             a2.val.f = a2.val.i;        /* truncate */
  1669.         }
  1670.     }
  1671.     result.type = a1.type;
  1672.  
  1673.     /* do the op */
  1674.  
  1675.     if(result.type == INT) {
  1676.         switch(op) {
  1677.             case '+':        result.val.i = a1.val.i + a2.val.i; break;
  1678.             case '-':        result.val.i = a1.val.i - a2.val.i; break;
  1679.             case '*':        result.val.i = a1.val.i * a2.val.i; break;
  1680.             case '/':        result.val.i = a1.val.i / a2.val.i; break;
  1681.             case '%':        result.val.i = a1.val.i % a2.val.i; break;
  1682.             case SHL:        result.val.i = a1.val.i << a2.val.i; break;
  1683.             case SHR:        result.val.i = a1.val.i >> a2.val.i; break;
  1684.             case '|':        result.val.i = a1.val.i | a2.val.i; break;
  1685.             case '&':        result.val.i = a1.val.i & a2.val.i; break;
  1686.             case '^':        result.val.i = a1.val.i ^ a2.val.i; break;
  1687.         }
  1688.     } else {
  1689.         switch(op) {
  1690.             case '+':        result.val.f = a1.val.f + a2.val.f; break;
  1691.             case '-':        result.val.f = a1.val.f - a2.val.f; break;
  1692.             case '*':        result.val.f = a1.val.f * a2.val.f; break;
  1693.             case '/':        result.val.f = a1.val.f / a2.val.f; break;
  1694.             case '%':        result.val.f = (int)a1.val.f % (int)a2.val.f; break;
  1695.             case SHL:        result.val.f = (int)a1.val.f << (int)a2.val.f; break;
  1696.             case SHR:        result.val.f = (int)a1.val.f >> (int)a2.val.f; break;
  1697.             case '|':        result.val.f = (int)a1.val.f | (int)a2.val.f; break;
  1698.             case '&':        result.val.f = (int)a1.val.f & (int)a2.val.f; break;
  1699.             case '^':        result.val.f = (int)a1.val.f ^ (int)a2.val.f; break;
  1700.         }
  1701.     }
  1702.  
  1703.     return result;
  1704. }
  1705.  
  1706. struct n unary_op(op, a1)
  1707. int op;
  1708. struct n a1;
  1709. {
  1710.     struct n result;
  1711.  
  1712.     if(a1.type == UNDEF) {
  1713.         result.type = UNDEF;
  1714.         return result;
  1715.     }
  1716.  
  1717.     result.type = a1.type;
  1718.  
  1719.     /* do the op */
  1720.  
  1721.     if(result.type == INT) {
  1722.         switch(op) {
  1723.             case '-':        result.val.i = -a1.val.i; break;
  1724.             case '~':        result.val.i = ~a1.val.i; break;
  1725.         }
  1726.     } else {
  1727.         switch(op) {
  1728.             case '-':        result.val.f = -a1.val.f; break;
  1729.             case '~':        result.val.f = ~(int)a1.val.f; break;
  1730.         }
  1731.     }
  1732.  
  1733.     return result;
  1734. }
  1735.  
  1736. n2int(n)
  1737. struct n n;
  1738. {
  1739.     if(n.type == UNDEF)
  1740.         return UNDEF;
  1741.     else if(n.type == INT)
  1742.         return n.val.i;
  1743.     else
  1744.         return n.val.f;
  1745. }
  1746.  
  1747. n2frac(n)
  1748. struct n n;
  1749. {
  1750.     double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f;
  1751.  
  1752.     if(n.type == UNDEF)
  1753.         return UNDEF;
  1754.     else if(n.type == INT)
  1755.         return n.val.i;
  1756.     else if(n.val.f == -1.0)
  1757.         return 0x800000;
  1758.  
  1759.     adval -= (double)(int)adval;
  1760.     adval *= (double)0x800000;
  1761.     adval += 0.5;
  1762.  
  1763.     if(n.val.f >= 0.0)
  1764.         return adval;
  1765.     else
  1766.         return -adval;
  1767. }
  1768.  
  1769. extern struct {int n; char *name;} tok_tab[];
  1770. extern int n_tok;
  1771.  
  1772. char *tok_print(tok)
  1773. int tok;
  1774. {
  1775.     int i;
  1776.     static char buf[32];
  1777.  
  1778.     if(tok < 256) {
  1779.         sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF);
  1780.         return buf;
  1781.     } else {
  1782.         for(i = 0; i < n_tok; i++) {
  1783.             if(tok == tok_tab[i].n)
  1784.                 return tok_tab[i].name;
  1785.         }
  1786.     }
  1787.     return "*bogus*";
  1788. }
  1789.  
  1790. yyerror(s, a0, a1, a2, a3)
  1791. char *s, *a0, *a1, *a2, *a3;
  1792. {
  1793.     extern int error;
  1794.     char buf[1024];
  1795.  
  1796.     error++;
  1797.     sprintf(buf, s, a0, a1, a2, a3);
  1798.  
  1799.     if(pass == 2) {
  1800.         fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
  1801.             buf, tok_print(yychar));
  1802.         fprintf(stderr, "%s\n", cur_line);
  1803.         printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
  1804.             buf, tok_print(yychar));
  1805.     }
  1806. }
  1807.  
  1808. char *luntab(s)
  1809. char *s;
  1810. {
  1811.     static char buf[1024];
  1812.     int p;
  1813.  
  1814.     strcpy(buf, s);
  1815.  
  1816.     untab(buf);
  1817.     p = strlen(buf);
  1818.  
  1819.     if(buf[p - 1] == '\n')
  1820.         buf[p - 1] = '\0';
  1821.  
  1822.     return buf;
  1823. }
  1824.